<template>
  <article class="page page-jwt">
    <h4 class="text-center">JSON Web Token</h4>
    <form class="form row">
      <div class="col-6 left">
        <fieldset>
          <legend>Encode</legend>
          <div class="fieldset-content">
            <textarea class="form-control" v-model.trim="valueEncode" @change="encodeChange"
              placeholder="ENCODE"></textarea>
            <!-- <div class="verify-result text-grey">{{ verifyResult }}</div> -->
          </div>
        </fieldset>
      </div>
      <div class="col-6 right">
        <fieldset>
          <legend>Decode</legend>
          <div class="fieldset-content">
            <div class="card">
              <div class="card-header">Algorithm</div>
              <div class="card-body">
                <select class="form-control" v-model="algorithm" @change="decodeChange">
                  <option v-for="(v, i) in algorithmList" :key="i" :value="v.value">{{ v.label }}</option>
                </select>
              </div>
            </div>
            <div class="card">
              <div class="card-header">HEADER:<span class="text-grey">ALGORITHM & TOKEN TYPE</span></div>
              <div class="card-body">
                <textarea class="form-control" v-model.trim="valueHeader" @change="decodeChange"></textarea>
              </div>
            </div>
            <div class="card">
              <div class="card-header">PAYLOAD:<span class="text-grey">DATA</span></div>
              <div class="card-body">
                <textarea class="form-control" v-model.trim="valuePayload" @change="decodeChange"></textarea>
              </div>
            </div>
            <div class="card">
              <div class="card-header">PrivateKey</div>
              <div class="card-body">
                <textarea class="form-control" v-model.trim="cert" @change="decodeChange"></textarea>
              </div>
            </div>
            <!-- <div class="card">
              <div class="card-header">VERIFY SIGNATURE</div>
              <div class="card-body">
                <input class="form-control" v-model.trim="signature" readonly />
              </div>
            </div> -->
          </div>
        </fieldset>
      </div>
    </form>
  </article>
</template>

<script>
let jsonwebtoken = global.jsonwebtoken || null

export default {
  name: 'jwt',
  data() {
    return {
      // Verify
      verifyResult: '',
      // Encode
      valueEncode: '',
      // Decode
      cert: 'secret',
      valueHeader: '',
      valuePayload: '',
      signature: '',
      algorithm: 'HS256',
      algorithmList: [
        { value: 'HS256', label: 'HS256', func: 'HMACSHA256' },
        { value: 'HS384', label: 'HS384', func: 'HMACSHA384' },
        { value: 'HS512', label: 'HS512', func: 'HMACSHA512' },
        { value: 'RS256', label: 'RS256', func: 'RSASHA256' },
        { value: 'RS384', label: 'RS384', func: 'RSASHA384' },
        { value: 'RS512', label: 'RS512', func: 'RSASHA512' },
        { value: 'ES256', label: 'ES256', func: 'ECDSASHA256' },
        { value: 'ES384', label: 'ES384', func: 'ECDSASHA384' },
        { value: 'ES512', label: 'ES512', func: 'ECDSASHA512' },
        { value: 'PS256', label: 'PS256', func: 'RSAPSSSHA256' },
        { value: 'PS384', label: 'PS384', func: 'RSAPSSSHA384' },
        { value: 'PS512', label: 'PS512', func: 'RSAPSSSHA512' },
      ]
    }
  },
  mounted() {
    jsonwebtoken = this.$sharedObject('jsonwebtoken')
    this.valueEncode = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c'
    this.encodeChange()
  },
  methods: {
    // encode数据变化
    encodeChange() {
      let decoded = jsonwebtoken.decode(this.valueEncode, { complete: true })
      this.valueHeader = JSON.stringify(decoded.header || {})
      this.valuePayload = JSON.stringify(decoded.payload || {})
      this.signature = decoded.signature || ''
    },
    // decode数据变化
    decodeChange() {
      let _this = this
      let cert = this.verifyCert()
      try {
        _this.valueEncode = jsonwebtoken.sign(_this.$jstools.jsonParse(_this.valuePayload), cert, {
          algorithm: _this.algorithm
        })
      }catch (err) {
        console.log(err)
        _this.$toast('请核查秘钥是否正确')
      }
    },
    // 修正cert
    verifyCert () {
      let cert = this.cert || 'secret'
      if (!['HS256', 'HS384', 'HS512'].includes(this.algorithm)) {
        cert = Buffer.from(cert)
      }
      return cert
    },
    // 校验
    verifyValue() {
      let cert = this.verifyCert()
      jsonwebtoken.verify(this.valueEncode, cert, (err, decoded) => {
        console.log(err, decoded)
        if (err) {
          this.verifyResult = 'Invalid Signature'
          this.$toast(err)
        } else {
          this.verifyResult = 'Signature Verified'
        }
      })
    },
  }
}
</script>

<style scoped lang="less">
@import "~@/assets/css/_mixins.less";
@import "~@/assets/css/_color.less";

.page-jwt {
  display: flex;
  flex-direction: column;

  .form {
    flex-grow: 1;

    fieldset {
      height: 100%;

      .fieldset-content {
        height: calc(100% - 2em);
        display: flex;
        flex-direction: column;
        position: relative;

        .verify-result {
          margin-top: .5em;
        }
      }
    }

    .left {
      textarea {
        flex-grow: 1;
      }
    }

    .right {
      .card {
        & + .card {
          flex-grow: 1;
          margin-top: .5em;
          textarea {
            height: 100%;
          }
        }
      }
    }
  }
}
</style>
